package com.aktk.battlenole;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.os.AsyncTask;
import android.util.Log;
import android.view.View.OnClickListener;

import com.aktk.battlenole.GameData.LastResult;
import com.aktk.battlenole.GameData.Stages;
import com.aktk.gameelements.GamePlay;
import com.aktk.gameelements.Ship;
import com.aktk.gameelements.GamePlay.Orientation;
import com.aktk.gameelements.GamePlay.SegmentType;
import com.aktk.gameelements.Player;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

public class MultiGameActivity extends Activity implements View.OnClickListener, BoardManager.OnClickListener {
	final int boardWidth = 10;
	final int boardHeight = 10;
	TextView message;
	TextView shipStatus;
	boolean shotFired;
	private int lastShotRow = -1;
	private int lastShotCol = -1;
	
	public enum BoardView {
		 PLAYER , OPPONENT;
	}
	BoardView view;
	
	GameData game;
	Player player;
	BoardManager manager;
	TextView bPlayerBoard;
	TextView bOpponentBoard;
	//Player currentTurn;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.multi_activity_game);
        game = new GameData();
        shotFired = false;
        game.shotCount = 1;
        
        LinearLayout playerBoardContainer = (LinearLayout)this.findViewById(R.id.playerContainer);
        manager = new BoardManager (boardWidth, boardHeight);
        manager.setOnClickListener(this);
        manager.Draw(this, playerBoardContainer);
        
        player = game.p1;
        
        message = (TextView)findViewById(R.id.messageLabel);
        message.setBackgroundColor(Color.parseColor("#90FFFFFF"));
        message.setTextColor(Color.BLACK);
        message.setOnClickListener(this);
        setMessage();
        
        bPlayerBoard = (TextView)findViewById(R.id.boardSelect1);
        bPlayerBoard.setText("My Board");
        bPlayerBoard.setOnClickListener(this);
        bPlayerBoard.setBackgroundColor( Color.BLACK );
        bPlayerBoard.setTextColor(Color.WHITE);
        bOpponentBoard = (TextView)findViewById(R.id.boardSelect2);
        bOpponentBoard.setText("Enemy Map");
        bOpponentBoard.setOnClickListener(this);
        bOpponentBoard.setBackgroundColor( Color.WHITE );
        bOpponentBoard.setTextColor(Color.BLACK);
        view = BoardView.OPPONENT;
        
        shipStatus = (TextView)findViewById(R.id.shipsRemaining);
        shipStatus.setText("Your ships remaining: " + Integer.toString(player.getShipsRemaining()));
        shipStatus.setBackgroundColor(Color.parseColor("#90FFFFFF"));
        shipStatus.setTextColor(Color.BLACK);
        mapRefresh();
        if(game.PlayerID == 1) 
        {
        	setGameJoinAlert();
        }
    }

	@Override
	public void onClick(View v) {
		if( v.getId() == bPlayerBoard.getId() )
		{
			bPlayerBoard.setBackgroundColor( Color.WHITE );
			bPlayerBoard.setTextColor(Color.BLACK);
			bOpponentBoard.setBackgroundColor( Color.BLACK );
			bOpponentBoard.setTextColor(Color.WHITE);
			boardRefresh();
			view = BoardView.PLAYER;
		}
		
		if( v.getId() == bOpponentBoard.getId() )
		{
			bOpponentBoard.setBackgroundColor( Color.WHITE );
			bOpponentBoard.setTextColor(Color.BLACK);
			bPlayerBoard.setBackgroundColor( Color.BLACK );
			bPlayerBoard.setTextColor(Color.WHITE);
			mapRefresh();
			view = BoardView.OPPONENT;
		}
		
		if( v.getId() == message.getId() )
		{
				refreshFromServer();
		}
	}
	
	public void boardRefresh(){
		ArrayList<BoardCellState> states = manager.getStates();
		
		for (int index = 0; index < 100; index++)
		{
			if( player.incommingShots.getResult(index) == SegmentType.HIT )
			{
				states.get(index).setState(SegmentType.NONE, true, Orientation.HORIZONTAL);
			}
			else
			{
				states.get(index).setState(SegmentType.NONE, false, Orientation.HORIZONTAL);
			}
		}
		
		for (int a = 0; a < player.getFleetSize(); ++a )
		{
			Ship currentShip = player.getShip(a);
			if( currentShip.getUsed() )
			{
				for( int b = 0 ; b < currentShip.getLength() ; ++b )
				{
					int cellNumber = currentShip.getShipCellNumber( b, boardWidth );
					states.get( cellNumber ).setState(currentShip.getShipSegmentType(b), currentShip.getHit(b), currentShip.getOrientation());
				}
			}
		}
		shipStatus.setText("Your ships remaining: " + Integer.toString(player.getShipsRemaining()));
		manager.setStatus(states);

    }
	
	private void mapRefresh() {
		ArrayList<BoardCellState> states = manager.getStates();
		for (int index = 0; index < states.size(); index++)
		{
			states.get( index ).setState(player.opponentMap.getResult( index ) , Orientation.HORIZONTAL );
		}
		manager.setStatus(states);
	}
	
	private void setMessage() {
		if( game.lr == LastResult.HIT )
		{
			Toast.makeText(getApplicationContext(), "Your opponent made a direct Hit!", Toast.LENGTH_LONG).show();
		}
		if( game.lr == LastResult.MISS )
		{
			Toast.makeText(getApplicationContext(), "Your opponent missed.", Toast.LENGTH_LONG).show();
		}
		message.setText("Select 'Enemy Map' to fire a missile or 'My Board' to review your ships." + " (GameID: " + Integer.toString(game.gameID) + ")" );
	}
	
	private void setGameJoinAlert() {
		AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
 
			alertDialogBuilder.setTitle("Game Setup");
			
			alertDialogBuilder.setMessage("Join game using GameID: " + Integer.toString(game.gameID));
	 
	        alertDialogBuilder.setNeutralButton("Done", new DialogInterface.OnClickListener() {
	                public void onClick(DialogInterface dialog, int which) {
	                	dialog.cancel();
	                }
	        }
	        
	    );
	        
		AlertDialog alertDialog = alertDialogBuilder.create();
		alertDialog.show();
	        
	        
	}
	
	private void setGameOverAlert( String str) {
		AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
 
			alertDialogBuilder.setTitle("Game Over");
			
			alertDialogBuilder.setMessage(str);
	 
	        alertDialogBuilder.setNeutralButton("Done", new DialogInterface.OnClickListener() {
	                public void onClick(DialogInterface dialog, int which) {
	                	Intent i = new Intent(MultiGameActivity.this, MainActivity.class);
    					startActivity (i);
	                }
	        }
	        
	    );
	        
		AlertDialog alertDialog = alertDialogBuilder.create();
		alertDialog.show();
	        
	        
	}
	
	@Override
	public void onClick(int row, int col) {
		if( view == BoardView.OPPONENT && shotFired == false && player.opponentMap.getResult(row, col) == SegmentType.NULL )
		{
			shotFired = true;
			boolean canShoot = false;
            if( GameData.PlayerID == 1 ) {
                // You can only shoot if this is true
                if(GameData.shotCount % 2 != 0) {
                    canShoot = true;
                }
            } 
            else // playerID == 2
            {
                // You can only shoot if this is true
                if(GameData.shotCount % 2 == 0) {
                    canShoot = true;
                }
            }

            if(canShoot) {
                player.opponentMap.setResult(row, col, SegmentType.NONE);
                lastShotRow = row;
                lastShotCol = col;
                mapRefresh();
                GameData.shotCount++;
                String pn = "Player" + Integer.toString(game.PlayerID);
                shootSubmit(GameData.gameID, row, col, pn, GameData.shotCount);
                //game.loopCounter = 1;
                message.setText("Press for updated game status.  Please press only once per few seconds.");
                 
            } else {
                message.setText("It is still other players turn. Please Refresh");
                new Handler().postDelayed(new Runnable() {
        		    @Override
        	        public void run() {
        		    	message.setText("Press for updated game status.  Please press only once per few seconds.");
        	        }
        	    }, 1000);
            }
		}
	}
	
	/*public void refreshLoop( ) {
		new Handler().postDelayed(new Runnable() {
		    @Override
	        public void run() {
		    	if( game.loopCounter < 100 && (GameData.shotCount % 2) == (game.PlayerID % 2))
		    	{
		    		refreshFromServer();
		    		refreshLoop();
		    	}
	        }
	    }, 6000);
	}*/
	
    // ///////////// SERVER CODE STARTS HERE/////////////
    // ///////////// SERVER CODE STARTS HERE/////////////
    // ///////////// SERVER CODE STARTS HERE/////////////

  //Use this to "Fire a shot"
    public void shootSubmit(int gameID, int x, int y, String player, int ShotCount){
        shootSubmit(String.valueOf(gameID), String.valueOf(x), String.valueOf(y), player, String.valueOf(ShotCount));
    } // optional helper method, if you don't want to manually convert to strings
    
    // You can either convert to string yourself or not
    public void shootSubmit(String gameID, String x, String y, String player, String ShotCount){
        String tempString = "gameID=" + gameID + "&x=" + x + "&y=" + y + "&player=" + player + "&shot=" + ShotCount;
        new ShootTask().execute("http://newrog.com/battle/shoot.php?" + tempString, "1");
    }
    
    // Use this to request updated shot from server
    private void refreshFromServer(){
        message.setText("Updating...");
        new RefreshTask().execute("http://newrog.com/battle/select.php?gameID=" + GameData.gameID);
    }

    // This method is called, providing the newly received data
    private void getUpdatedLastShot(int gameID, String playerName, int xShot, int yShot, int shotCount){

        new DidMyLastShotSubmit().execute("http://newrog.com/battle/hitCheck.php?gameID=" + GameData.gameID + "&ShotCount="
            + (GameData.shotCount));

        System.out.println(shotCount + " " + GameData.shotCount);
        // Is it a NEW shot?
        if(shotCount > GameData.shotCount) {
            GameData.shotCount = shotCount;
            shotFired = false;
            //boolean hitCheck = player.inMissile(xShot, yShot);
            int hit;
            if( player.inMissile(xShot, yShot) )
            {
        		//message.setText("Direct Hit!");
        		//Toast.makeText(getApplicationContext(), "Direct Hit", Toast.LENGTH_SHORT).show();
        		game.lr = LastResult.HIT;
        		hit = 1;
        		if(player.getShipsRemaining() == 0) {
                    hit = 2; // 2 is end game condition
                    setGameOverAlert( "You lost!" );
                }
            }
            else
            {
        		//message.setText("Miss.");
        		//Toast.makeText(getApplicationContext(), "Splash - Miss.", Toast.LENGTH_SHORT).show(); 	
        		game.lr = LastResult.MISS;
        		hit = 0;
            }
            //boardRefresh();
            setMessage();
            mapRefresh();
            updateServerForHitCheck();
            //int hit = hitCheck ? 1 : 0;
            String str = "&gameID=" + GameData.gameID + "&ShotCount=" + shotCount + "&Hit=" + hit;
            new SubmitHit().execute("http://newrog.com/battle/hit.php?" + str);
        }

    }
    

	/*if ( player.fireMissileServer( row,  col ) ) // Hit
	{
		player.opponentMap.setResult( row , col , SegmentType.HIT );
		mapRefresh();
		message.setText("Direct Hit!");
		Toast.makeText(getApplicationContext(), "Direct Hit", Toast.LENGTH_SHORT).show();
	}
	else // Miss
	{
		player.opponentMap.setResult( row , col , SegmentType.MISS );
		mapRefresh();
		message.setText("Miss.");
		Toast.makeText(getApplicationContext(), "Splash - Miss.", Toast.LENGTH_SHORT).show();
	}*/

    private void updateServerForHitCheck(){
    }

    //For shooting, needs work
    class ShootTask extends AsyncTask<String, String, String> {
        boolean CreatingGame;

        @Override
        protected String doInBackground(String... uri){
            String responseString = easyHttpCode(uri[0]);
            return responseString;
        }

        @Override
        protected void onPostExecute(String result){
            super.onPostExecute(result);
            // parse json data
            String[] split = result.split(" ");
            int tempGameID = Integer.valueOf(split[0]);
            int ro = Integer.valueOf(split[1]);
            int co = Integer.valueOf(split[2]);

            if(tempGameID == GameData.gameID) {
                player.opponentMap.setResult(ro, co, SegmentType.WHOLE);
            } else {
                player.opponentMap.setResult(lastShotRow, lastShotCol, SegmentType.NONE);
            }
            mapRefresh();
        }
    }

    
    //this is supposed to be used to send back to the other player if they hit or miss
    class SubmitHit extends AsyncTask<String, String, String> {
        @Override
        protected String doInBackground(String... uri){
            String responseString = easyHttpCode(uri[0]);
            return responseString;
        }

        @Override
        protected void onPostExecute(String result){
            super.onPostExecute(result);
            message.setText("Press for updated game status.  Please press only once per few seconds.");
        }
    }

    
 
    class DidMyLastShotSubmit extends AsyncTask<String, String, String> {
        @Override
        protected String doInBackground(String... uri){
            String responseString = easyHttpCode(uri[0]);
            return responseString;
        }

        @Override
        protected void onPostExecute(String result){
            super.onPostExecute(result);
            try {
                JSONArray jArray = new JSONArray(result);
                int gameID = -1;
                int hit = -1;
                for(int i = 0; i < jArray.length(); i++) {
                    JSONObject json_data = jArray.getJSONObject(i);
                    gameID = json_data.getInt("gameID");
                    hit = json_data.getInt("Hit");
                }
                if(hit == 0)
                    player.opponentMap.setResult(lastShotRow, lastShotCol, SegmentType.MISS);
                else if(hit == 1) player.opponentMap.setResult(lastShotRow, lastShotCol, SegmentType.HIT);
                else if( hit == 2 )
                {
                	setGameOverAlert( "You Won!" );
                }
                mapRefresh();

            } catch (JSONException e) {
                Log.e("log_tag", "Error parsing data2 " + e.toString());
            }
            message.setText("Updated");
        }
    }

    class RefreshTask extends AsyncTask<String, String, String> {

        @Override
        protected String doInBackground(String... uri){
            String responseString = easyHttpCode(uri[0]);
            return responseString;
        }

        @Override
        protected void onPostExecute(String result){
            super.onPostExecute(result);
            // parse json data
            try {
                JSONArray jArray = new JSONArray(result);
                int gameID = -1;
                String playerName = "";
                int xShot = -1;
                int yShot = -1;
                int shotCount = -1;
                for(int i = 0; i < jArray.length(); i++) {
                    JSONObject json_data = jArray.getJSONObject(i);
                    //playerName = json_data.getString("Player");
                    gameID = json_data.getInt("gameID");
                    xShot = json_data.getInt("x");
                    yShot = json_data.getInt("y");
                    shotCount = json_data.getInt("ShotCount");
                }
                getUpdatedLastShot(gameID, playerName, xShot, yShot, shotCount);
            } catch (JSONException e) {
                Log.e("log_tag", "Error parsing data3 " + e.toString());
            }

        }
    }

    //helper code to reduce redundancy
    private String easyHttpCode(String s){
        System.out.println(s);
        HttpClient httpclient = new DefaultHttpClient();
        HttpResponse response;
        String responseString = null;
        try {
            response = httpclient.execute(new HttpGet(s));

            StatusLine statusLine = response.getStatusLine();
            if(statusLine.getStatusCode() == HttpStatus.SC_OK) {
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                response.getEntity().writeTo(out);
                out.close();
                responseString = out.toString();
            } else {
                // Closes the connection.
                response.getEntity().getContent().close();
                throw new IOException(statusLine.getReasonPhrase());
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return responseString;
    }


}
